
(function () {
    nsbase.utility.functions = new Func();

    function Func() {
        var _self = this;

        function _init() {
            _self.getCurrentFunctionName = getCurrentFunctionName;
            _self.argumentsToArray = argumentsToArray;
            _self.isDate = isDate;
            _self.isString = isString;
            _self.isObject = isObject;
            _self.isNumber = isNumber;
            _self.isBoolean = isBoolean;
            _self.isArray = isArray;
            _self.iRegExp = iRegExp;
            _self.isFunction = isFunction;

            _self.autoInitialize = autoInitialize;
        }
        
        function getCurrentFunctionName(funcBody) {
            /// <signature>
            ///   <summary>
            ///     Get the name of a specific function. Note that the current function must be decared as: function FuncName() { }.
            ///     If the current function is an anonymous function, the result will be empty string.
            ///   </summary>
            ///   <param name="funcBody" type="Function">The function constructor to extract function name from.</param>
            ///   <returns type="String">The name of current invoking function.</returns>
            /// </signature>
            /// <signature>
            ///   <summary>
            ///     Get the name of a specific function. Note that the current function must be decared as: function FuncName() { }.
            ///     If the current function is an anonymous function, the result will be empty string.
            ///   </summary>
            ///   <param name="funcBody" type="String">The string content of function constructor to extract function name from. It can be got from Func.toString().</param>
            ///   <returns type="String">The name of current invoking function.</returns>
            /// </signature>
            /// <signature>
            ///   <summary>
            ///     Get the name of current invoking function method. Note that the current function must be decared as: function FuncName() { }.
            ///     If the current function is an anonymous function, the result will be empty string.
            ///   </summary>
            ///   <returns type="String">The name of current invoking function.</returns>
            /// </signature>
            var functionNameRegex = /^function\s*?(\w+?)\s*?\(/i;
            if (typeof funcBody == "function") {
                funcBody = funcBody.toString();
            }
            funcBody = funcBody || arguments.callee.caller.toString();
            var functionNameMatch = funcBody.match(functionNameRegex);
            if (functionNameMatch) {
                return functionNameMatch[1];
            }
            else {
                return "";
            }
        }

        function argumentsToArray(arguments_object) {
            /// <summary>
            /// Converts the function 'arguments' object to an array.
            /// </summary>
            /// <param name="arguments_object" type="Object">The arguments object to array.</param>
            /// <returns type="Array">The array of arguments elements.</returns>
            return Array.prototype.slice.apply(arguments_object, Array.prototype.slice.call(arguments, 1));
        }

        function getClass(object) {
            return Object.prototype.toString.call(object).match(/^\[object\s(.*)\]$/)[1];
        };

        function isDate(obj) {
            return (getClass(obj) == "Date");
        }

        function isString(obj) {
            return (getClass(obj) == "String");
        }

        function isObject(obj) {
            return (getClass(obj) == "Object");
        }

        function isNumber(obj) {
            return (getClass(obj) == "Number");
        }

        function isBoolean(obj) {
            return (getClass(obj) == "Boolean");
        }

        function isArray(obj) {
            return (getClass(obj) == "Array");
        }

        function iRegExp(obj) {
            return (getClass(obj) == "RegExp");
        }

        function isFunction(obj, check_constructor) {
            if (constructor == null) {
                return (typeof obj == "function");
            }
            else {
                if (obj == null) {
                    return false;
                }
                else {
                    return (obj.constructor == check_constructor);
                }
            }
        }

        function autoInitialize(instance, initializer) {
            /// <signature>
            ///   <summary>
            ///     Initialize an instance by auto-initializer object. The members of instance will be assigned from initializer one by one according to member name.
            ///   </summary>
            ///   <param name="instance" type="Object">The instance to be initialized.</param>
            ///   <param name="initializer" type="Object">The auto initializer object. The members are organized by a plain object. For example, {name: "my name", age: 25}.</param>
            /// </signature>

            if (initializer != null) {
                for (var key in initializer) {
                    if (initializer.hasOwnProperty(key)) {
                        if (!instance.hasOwnProperty(key)) {
                            throw new Error("The member '" + key + "' of initializer '" + nsbase.controls.editor.utility.toJsonString(initializer) + "' is not recognized by '" + nsbase.utility.functions.getCurrentFunctionName(arguments.callee.caller) + "'.");
                        }
                    }
                }
                $.extend(instance, initializer);
            }
        };

        _init();
    };
})();
